﻿// <copyright file="Database.cs" company="Hallvard Korsgaard">
//  Microsoft Public License (Ms-PL). See license details here: http://enoceannet.codeplex.com/license
// </copyright>
// <author>Hallvard Korsgaard</author>

namespace SqlLogger.DataAccess
{
  using System;
  using System.Configuration;
  using System.Data;
  using System.Data.SqlClient;

  /// <summary>
  /// Wrapper methods for SQL Server stored procedures.
  /// </summary>
  internal static class Database
  {
    /// <summary>
    /// Calls the StoreSwitch stored procedure.
    /// </summary>
    /// <param name="sensorId">The sensor id.</param>
    /// <param name="created">The time the event occurred.</param>
    /// <param name="energyBowPressed">True if the energy bow was pressed.</param>
    /// <param name="button">Id of the pressed button.</param>
    /// <param name="buttonState">True if button was pressed, false if it was released or null if it was not used.</param>
    internal static void StoreSwitch(long sensorId, DateTimeOffset created, bool energyBowPressed, byte button, bool? buttonState)
    {
      SqlConnection con;
      SqlCommand cmd;

      using (con = new SqlConnection(GetConnectionString()))
      {
        con.Open();

        using (cmd = new SqlCommand("StoreSwitch", con))
        {
          cmd.CommandType = CommandType.StoredProcedure;

          cmd.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.BigInt)
          {
            Value = sensorId
          });

          cmd.Parameters.Add(new SqlParameter("@Created", SqlDbType.DateTimeOffset)
          {
            Value = created
          });

          cmd.Parameters.Add(new SqlParameter("@EnergyBowPressed", SqlDbType.Bit)
          {
            Value = energyBowPressed
          });

          cmd.Parameters.Add(new SqlParameter("@Button", SqlDbType.TinyInt)
          {
            Value = button
          });

          if (buttonState != null)
          {
            cmd.Parameters.Add(new SqlParameter("@ButtonState", SqlDbType.Bit)
            {
              Value = buttonState,
              IsNullable = true
            });
          }
          else
          {
            cmd.Parameters.Add(new SqlParameter("@ButtonState", SqlDbType.Bit)
            {
              Value = DBNull.Value,
              IsNullable = true
            });
          }
          
          cmd.ExecuteNonQuery();
        }

        con.Close();
      }
    }

    /// <summary>
    /// Calls the StoreDigitalSensor stored procedure.
    /// </summary>
    /// <param name="sensorId">The sensor id.</param>
    /// <param name="sensorType">The type of sensor.</param>
    /// <param name="created">The time the event occurred.</param>
    /// <param name="value">The sensor output.</param>
    internal static void StoreDigitalSensor(long sensorId, SensorType sensorType, DateTimeOffset created, bool value)
    {
      SqlConnection con;
      SqlCommand cmd;

      using (con = new SqlConnection(GetConnectionString()))
      {
        con.Open();

        using (cmd = new SqlCommand("StoreDigitalSensor", con))
        {
          cmd.CommandType = CommandType.StoredProcedure;

          cmd.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.BigInt)
          {
            Value = sensorId
          });

          cmd.Parameters.Add(new SqlParameter("@SensorType", SqlDbType.Int)
          {
            Value = (int)sensorType
          });

          cmd.Parameters.Add(new SqlParameter("@Created", SqlDbType.DateTimeOffset)
          {
            Value = created
          });

          cmd.Parameters.Add(new SqlParameter("@Value", SqlDbType.Bit)
          {
            Value = value
          });

          cmd.ExecuteNonQuery();
        }

        con.Close();
      }
    }

    /// <summary>
    /// Calls the StoreAnalogSensor stored procedure.
    /// </summary>
    /// <param name="sensorId">The sensor id.</param>
    /// <param name="sensorType">The type of sensor.</param>
    /// <param name="created">The time the event occurred.</param>
    /// <param name="rawValue">The output from the sensor.</param>
    /// <param name="realValue">The sensor output value converted to something human readable, e.g. the temperature in celcius.</param>
    internal static void StoreAnalogSensor(long sensorId, SensorType sensorType, DateTimeOffset created, byte rawValue, decimal realValue)
    {
      SqlConnection con;
      SqlCommand cmd;

      using (con = new SqlConnection(GetConnectionString()))
      {
        con.Open();

        using (cmd = new SqlCommand("StoreAnalogSensor", con))
        {
          cmd.CommandType = CommandType.StoredProcedure;

          cmd.Parameters.Add(new SqlParameter("@SensorId", SqlDbType.BigInt)
          {
            Value = sensorId
          });

          cmd.Parameters.Add(new SqlParameter("@SensorType", SqlDbType.Int)
          {
            Value = (int)sensorType
          });

          cmd.Parameters.Add(new SqlParameter("@Created", SqlDbType.DateTimeOffset)
          {
            Value = created
          });

          cmd.Parameters.Add(new SqlParameter("@RawValue", SqlDbType.TinyInt)
          {
            Value = rawValue
          });

          cmd.Parameters.Add(new SqlParameter("@RealValue", SqlDbType.Decimal)
          {
            Precision = 11,
            Scale = 4,
            Value = realValue
          });

          cmd.ExecuteNonQuery();
        }

        con.Close();
      }
    }

    /// <summary>
    /// Reads the connection string from the config file.
    /// </summary>
    /// <returns>The connection string.</returns>
    private static string GetConnectionString()
    {
      return ConfigurationManager.ConnectionStrings["LogDatabase"].ConnectionString;
    }
  }
}
